const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const path = require('path');
const cors = require('cors');
const fs = require('fs');
const Database = require('./database');
const { v4: uuidv4 } = require('uuid');

// 创建Express应用
const app = express();

// 启用CORS
app.use(cors());

// 提供静态文件
app.use(express.static(path.join(__dirname, '../frontend')));

// API路由
// 获取日志
app.get('/api/logs', async (req, res) => {
    try {
        const { 
            page = 1, 
            limit = 100, 
            level, 
            module, 
            startTime, 
            endTime, 
            search,
            deviceId,
            sessionId,
            deduplicated = 'true'
        } = req.query;
        
        const offset = (parseInt(page) - 1) * parseInt(limit);
        
        const filters = {};
        if (level) filters.level = level;
        if (module) filters.module = module;
        if (search) filters.search = search;
        if (deviceId) filters.deviceId = deviceId;
        if (sessionId) filters.sessionId = sessionId;
        if (startTime) filters.startTime = startTime;
        if (endTime) filters.endTime = endTime;
        
        let logs, total;
        
        if (deduplicated === 'true') {
            // 使用去重日志
            logs = await database.getDeduplicatedLogs(parseInt(limit), offset, filters);
            total = await database.getDeduplicatedLogCount(filters);
        } else {
            // 使用原始日志
            logs = await database.getLogs(parseInt(limit), offset, filters);
            total = await database.getLogCount(filters);
        }
        
        res.json({
            success: true,
            data: {
                logs,
                pagination: {
                    page: parseInt(page),
                    limit: parseInt(limit),
                    total,
                    totalPages: Math.ceil(total / parseInt(limit))
                },
                deduplicated: deduplicated === 'true'
            }
        });
    } catch (error) {
        console.error('获取日志失败:', error);
        res.status(500).json({
            success: false,
            error: '获取日志失败'
        });
    }
});

// 获取日志统计信息
app.get('/api/logs/stats', async (req, res) => {
    try {
        const { startTime, endTime, deduplicated = 'true' } = req.query;
        
        const filters = {};
        if (startTime) filters.startTime = startTime;
        if (endTime) filters.endTime = endTime;
        
        let stats;
        if (deduplicated === 'true') {
            stats = await database.getDeduplicatedLogStats(filters);
        } else {
            stats = await database.getLogStats(filters);
        }
        
        res.json({
            success: true,
            data: {
                ...stats,
                deduplicated: deduplicated === 'true'
            }
        });
    } catch (error) {
        console.error('获取日志统计失败:', error);
        res.status(500).json({
            success: false,
            error: '获取日志统计失败'
        });
    }
});

// 清除日志
app.delete('/api/logs', async (req, res) => {
    try {
        const { days = 0 } = req.query;
        
        if (days > 0) {
            await database.cleanupOldLogs(parseInt(days));
        } else {
            // 清除所有日志和历史会话
            await database.clearAllLogs();
        }
        
        let message;
        if (days > 0) {
            message = `已清除${days}天前的日志`;
        } else {
            message = '已清除所有日志和历史会话';
        }
        
        res.json({
            success: true,
            message: message
        });
    } catch (error) {
        console.error('清除日志失败:', error);
        res.status(500).json({
            success: false,
            error: '清除日志失败'
        });
    }
});

// 获取设备列表的API
app.get('/api/devices', async (req, res) => {
    try {
        const devices = await database.getDevices();
        res.json(devices);
    } catch (error) {
        console.error('获取设备列表失败:', error);
        res.status(500).json({ error: '获取设备列表失败' });
    }
});

// 删除设备的API
app.delete('/api/devices/:deviceId', async (req, res) => {
    try {
        const { deviceId } = req.params;
        const result = await database.deleteDevice(deviceId);
        res.json({ success: true, message: '设备已成功删除', deviceId });
    } catch (error) {
        console.error('删除设备失败:', error);
        res.status(500).json({ error: '删除设备失败' });
    }
});

// 获取设备会话列表的API
app.get('/api/devices/:deviceId/sessions', async (req, res) => {
    try {
        const { deviceId } = req.params;
        const sessions = await database.getDeviceSessions(deviceId);
        res.json(sessions);
    } catch (error) {
        console.error('获取设备会话列表失败:', error);
        res.status(500).json({ error: '获取设备会话列表失败' });
    }
});

// 获取所有会话列表的API
app.get('/api/sessions', async (req, res) => {
    try {
        const sessions = await database.getAllSessions();
        res.json(sessions);
    } catch (error) {
        console.error('获取所有会话列表失败:', error);
        res.status(500).json({ error: '获取所有会话列表失败' });
    }
});

// 获取当前活跃设备的API
app.get('/api/active-devices', async (req, res) => {
    try {
        const activeDevices = [];
        deviceSessions.forEach((sessionInfo, deviceId) => {
            activeDevices.push(deviceId);
        });
        res.json(activeDevices);
    } catch (error) {
        console.error('获取活跃设备失败:', error);
        res.status(500).json({ error: '获取活跃设备失败' });
    }
});

// 获取设备启动统计信息
app.get('/api/device-stats/:deviceId?', async (req, res) => {
    try {
        const { deviceId } = req.params;
        const stats = await database.getDeviceStartupStats(deviceId || null);
        res.json({ success: true, data: stats });
    } catch (error) {
        console.error('获取设备统计失败:', error);
        res.status(500).json({ success: false, error: '获取设备统计失败' });
    }
});

// 删除设备的API
app.delete('/api/devices/:deviceId', async (req, res) => {
    try {
        const { deviceId } = req.params;
        const result = await database.deleteDevice(deviceId);
        
        if (result.deleted) {
            // 如果设备当前活跃，清理内存中的会话信息
            if (deviceSessions.has(deviceId)) {
                deviceSessions.delete(deviceId);
            }
            
            res.json({ 
                success: true, 
                message: `设备 ${deviceId} 已删除`,
                deviceId: result.deviceId
            });
        } else {
            res.status(404).json({ 
                success: false, 
                error: '设备不存在' 
            });
        }
    } catch (error) {
        console.error('删除设备失败:', error);
        res.status(500).json({ 
            success: false, 
            error: '删除设备失败' 
        });
    }
});

// 创建HTTP服务器
const server = http.createServer(app);

// WebSocket服务器
const wss = new WebSocket.Server({ server });

// 存储客户端连接
const clients = new Map(); // 改为Map以存储客户端ID和连接信息
const deviceSessions = new Map(); // 存储设备会话信息

// 数据库实例
const database = new Database();

// 性能优化配置
const BATCH_SIZE = 100; // 批量处理日志的大小
const BATCH_TIMEOUT = 1000; // 批量处理超时时间（毫秒）
let logBatch = [];
let batchTimer = null;

// WebSocket连接处理
wss.on('connection', async (ws, req) => {
    const clientId = uuidv4();
    let deviceId = null;
    let sessionId = null;
    
    const clientInfo = {
        id: clientId,
        ws: ws,
        ip: req.socket.remoteAddress,
        connectedAt: new Date(),
        isAlive: true,
        deviceId: null,
        sessionId: null
    };
    
    console.log(`客户端已连接: ${clientId} (${clientInfo.ip})`);
    
    // 将新客户端添加到Map中
    clients.set(clientId, clientInfo);
    
    // 发送最近的日志给新客户端
    try {
        const recentLogs = await database.getRecentLogs(100);
        recentLogs.forEach(log => {
            if (ws.readyState === WebSocket.OPEN) {
                ws.send(JSON.stringify({
                    id: log.id,
                    level: log.level,
                    module: log.module,
                    message: log.message,
                    timestamp: log.timestamp
                }));
            }
        });
    } catch (error) {
        console.error('发送历史日志失败:', error);
    }
    
    // 设置心跳检测
    ws.isAlive = true;
    ws.on('pong', () => {
        ws.isAlive = true;
    });
    
    // 处理接收到的消息
    ws.on('message', async (message) => {
        try {
            // 检查消息是否为空
            if (!message || message.length === 0) {
                console.log('收到空消息，忽略');
                return;
            }
            
            // console.log(`收到消息 (${clientId}): ${message.toString()}`);
            const data = JSON.parse(message);
            
            // 处理设备注册消息
            if (data.type === 'device_register') {
                try {
                    const { deviceName, description } = data;
                    deviceId = data.deviceId || uuidv4();
                    
                    // 创建或更新设备
                    const deviceResult = await database.createOrUpdateDevice(deviceId, deviceName, description);
                    
                    // 创建新会话
                    const sessionResult = await database.createSession(deviceId);
                    sessionId = sessionResult.sessionId;
                    
                    // 更新客户端信息
                    clientInfo.deviceId = deviceId;
                    clientInfo.sessionId = sessionId;
                    clients.set(clientId, clientInfo);
                    
                    // 存储设备会话信息
                    deviceSessions.set(deviceId, {
                        sessionId,
                        clientId,
                        deviceName,
                        startTime: new Date()
                    });
                    
                    console.log(`设备已注册: ${deviceName} (${deviceId}), 会话: ${sessionId}`);
                    
                    // 发送注册确认
                    ws.send(JSON.stringify({
                        type: 'device_registered',
                        deviceId,
                        sessionId,
                        deviceName
                    }));
                    
                } catch (error) {
                    console.error('设备注册失败:', error);
                    ws.send(JSON.stringify({
                        type: 'error',
                        message: '设备注册失败'
                    }));
                }
                return;
            }
            
            // 处理日志消息
            if (data.type === 'log' || !data.type) {
                const logData = data.type === 'log' ? data.data : data;
                
                // 验证日志数据格式
                if (!validateLogData(logData)) {
                    console.error('无效的日志数据格式');
                    return;
                }
                
                // 添加时间戳（如果没有）
                if (!logData.timestamp) {
                    logData.timestamp = new Date().toISOString();
                }
                
                // 检查是否为未注册设备的日志
                if (logData.deviceId && !deviceId) {
                    try {
                        // 自动注册设备
                        const autoDeviceId = logData.deviceId;
                        const autoDeviceName = `${autoDeviceId}`;
                        const autoDescription = '通过日志自动注册的设备';
                        
                        console.log(`自动注册设备: ${autoDeviceName} (${autoDeviceId})`);
                        
                        // 创建或更新设备
                        const deviceResult = await database.createOrUpdateDevice(autoDeviceId, autoDeviceName, autoDescription);
                        
                        // 创建新会话
                        const sessionResult = await database.createSession(autoDeviceId);
                        const autoSessionId = sessionResult.sessionId;
                        
                        // 更新客户端信息
                        deviceId = autoDeviceId;
                        sessionId = autoSessionId;
                        clientInfo.deviceId = deviceId;
                        clientInfo.sessionId = sessionId;
                        clients.set(clientId, clientInfo);
                        
                        // 存储设备会话信息
                        deviceSessions.set(deviceId, {
                            sessionId,
                            clientId,
                            deviceName: autoDeviceName,
                            startTime: new Date()
                        });
                        
                        console.log(`设备自动注册成功: ${autoDeviceName} (${autoDeviceId}), 会话: ${autoSessionId}`);
                        
                    } catch (error) {
                        console.error('自动注册设备失败:', error);
                    }
                }
                
                // 添加到批处理队列（使用去重功能）
                addToBatch(logData, clientId, deviceId, sessionId);
                
                // 立即广播给所有客户端
                broadcastLog(logData, deviceId, sessionId);
                
                // 更新会话日志计数
                if (sessionId) {
                    try {
                        await database.updateSessionLogCount(sessionId, 1);
                    } catch (error) {
                        console.error('更新会话日志计数失败:', error);
                    }
                }
            }
            
        } catch (error) {
            console.error('处理消息时出错:', error);
        }
    });
    
    // 处理连接断开
    ws.on('close', async () => {
        console.log(`客户端已断开连接: ${clientId}`);
        
        // 结束会话
        if (sessionId) {
            try {
                await database.endSession(sessionId);
                console.log(`会话已结束: ${sessionId}`);
            } catch (error) {
                console.error('结束会话失败:', error);
            }
        }
        
        // 清理设备会话信息
        if (deviceId) {
            deviceSessions.delete(deviceId);
        }
        
        clients.delete(clientId);
    });
    
    // 处理错误
    ws.on('error', (error) => {
        console.error(`WebSocket错误 (${clientId}):`, error);
        clients.delete(clientId);
    });
});

// 验证日志数据格式
function validateLogData(data) {
    // 必须包含级别和消息
    if (!data || 
        typeof data !== 'object' || 
        !data.level || 
        typeof data.level !== 'string' || 
        !data.message || 
        typeof data.message !== 'string') {
        return false;
    }
    
    // 如果包含module字段，必须是有效的字符串
    if (data.module !== undefined) {
        if (typeof data.module !== 'string' || data.module.trim() === '') {
            return false;
        }
    }
    
    return true;
}

// 添加日志到批处理队列
function addToBatch(logData, clientId, deviceId = null, sessionId = null) {
    logBatch.push({ 
        logData, 
        clientId, 
        deviceId, 
        sessionId 
    });
    
    // 如果批处理队列达到最大大小，立即处理
    if (logBatch.length >= BATCH_SIZE) {
        processBatch();
    } else if (!batchTimer) {
        // 设置定时器，确保日志不会等待太久
        batchTimer = setTimeout(processBatch, BATCH_TIMEOUT);
    }
}

// 处理批处理队列（使用去重功能）
async function processBatch() {
    if (logBatch.length === 0) {
        return;
    }
    
    const currentBatch = [...logBatch];
    logBatch = [];
    
    // 清除定时器
    if (batchTimer) {
        clearTimeout(batchTimer);
        batchTimer = null;
    }
    
    try {
        // 批量插入到数据库（使用去重功能）
        const logsWithDeviceInfo = currentBatch.map(item => ({
            ...item.logData,
            deviceId: item.deviceId,
            sessionId: item.sessionId
        }));
        
        const result = await database.insertDeduplicatedLogsBatch(logsWithDeviceInfo, currentBatch[0]?.clientId);
        
        console.log(`批量处理 ${result.insertedCount} 条新日志，${result.duplicateCount} 条重复日志`);
    } catch (error) {
        console.error('批量处理去重日志失败:', error);
        
        // 如果批量处理失败，尝试逐个插入
        for (const item of currentBatch) {
            try {
                const logWithDeviceInfo = {
                    ...item.logData,
                    deviceId: item.deviceId,
                    sessionId: item.sessionId
                };
                await database.insertDeduplicatedLog(logWithDeviceInfo, item.clientId);
            } catch (insertError) {
                console.error('单个去重日志插入失败:', insertError);
            }
        }
    }
}

// 广播日志给所有客户端
function broadcastLog(logData, deviceId = null, sessionId = null) {
    const message = JSON.stringify({
        type: 'log',
        data: {
            ...logData,
            deviceId: deviceId,
            sessionId: sessionId
        },
        timestamp: new Date().toISOString()
    });
    
    clients.forEach((clientInfo, clientId) => {
        const ws = clientInfo.ws;
        // 检查客户端是否仍然连接
        if (ws.readyState === WebSocket.OPEN) {
            try {
                ws.send(message);
            } catch (error) {
                console.error(`发送日志到客户端 ${clientId} 失败:`, error);
                // 移除无效的客户端
                clients.delete(clientId);
            }
        } else {
            // 移除已断开的客户端
            clients.delete(clientId);
        }
    });
}

// 将日志保存到文件（可选功能）
function saveLogToFile(logData) {
    // 创建日志目录（如果不存在）
    const logDir = path.join(__dirname, '../logs');
    if (!fs.existsSync(logDir)) {
        fs.mkdirSync(logDir, { recursive: true });
    }
    
    // 按日期创建日志文件
    const date = new Date();
    const fileName = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}.log`;
    const filePath = path.join(logDir, fileName);
    
    // 格式化日志条目
    const timestamp = new Date(logData.timestamp).toISOString();
    const level = logData.level.toUpperCase().padEnd(9);
    const module = logData.module ? `[${logData.module}]`.padEnd(15) : ''.padEnd(15);
    const message = logData.message;
    
    const logEntry = `${timestamp} ${level} ${module} ${message}\n`;
    
    // 追加到文件
    fs.appendFile(filePath, logEntry, (err) => {
        if (err) {
            console.error('保存日志到文件时出错:', err);
        }
    });
}

// 定义路由
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, '../frontend/index.html'));
});

// 心跳检测，定期检查客户端连接状态
setInterval(() => {
    clients.forEach((clientInfo, clientId) => {
        const ws = clientInfo.ws;
        if (!ws.isAlive) {
            console.log(`客户端 ${clientId} 心跳检测失败，断开连接`);
            ws.terminate();
            clients.delete(clientId);
            return;
        }
        
        ws.isAlive = false;
        ws.ping();
    });
}, 30000); // 每30秒检查一次

// 定期清理旧日志（可选）
setInterval(async () => {
    try {
        await database.cleanupOldLogs(30); // 保留30天的日志
    } catch (error) {
        console.error('清理旧日志失败:', error);
    }
}, 24 * 60 * 60 * 1000); // 每24小时清理一次

// 优雅关闭处理
process.on('SIGINT', async () => {
    console.log('\n正在关闭服务器...');
    
    // 处理剩余的批处理队列
    if (logBatch.length > 0) {
        console.log('处理剩余的日志批次...');
        await processBatch();
    }
    
    // 关闭数据库连接
    await database.close();
    
    // 关闭服务器
    server.close(() => {
        console.log('服务器已关闭');
        process.exit(0);
    });
});

// 初始化数据库并启动服务器
async function startServer() {
    try {
        // 初始化数据库
        await database.initialize();
        console.log('数据库初始化完成');
        
        // 启动服务器
        const PORT = process.env.PORT || 3333;
        server.listen(PORT, () => {
            console.log(`服务器运行在 http://localhost:${PORT}`);
            console.log(`WebSocket服务器运行在 ws://localhost:${PORT}`);
            console.log(`当前连接的客户端数量: ${clients.size}`);
        });
        
    } catch (error) {
        console.error('启动服务器失败:', error);
        process.exit(1);
    }
}

// 启动服务器
startServer();